The basics of pillow¶
create new image by import¶
In [1]:
from IPython.display import display
from PIL import Image
img = Image.open("fruits.png")
img # img.show() / show the picture
Out[1]:
alternative way to import an image
In [2]:
with Image.open("fruits.png") as img:
display(img) # img.show()
create a new image from scratch¶
In [3]:
new_img = Image.new(mode="RGBA",size=(300, 200))
new_img
Out[3]:
saving the picture
In [4]:
# img.save("test.png")
image information¶
In [5]:
img.size
Out[5]:
(300, 200)
In [6]:
img.filename
Out[6]:
'fruits.png'
In [7]:
img.format
Out[7]:
'PNG'
In [8]:
img.format_description
Out[8]:
'Portable network graphics'
Basic manipulation¶
Rotate¶
In [9]:
img_rotate = img.rotate(60)
img_rotate
Out[9]:
In [10]:
img_rotate = img.rotate(60,expand=True,fillcolor= (0, 128, 0))
img_rotate
Out[10]:
In [11]:
from PIL import ImageColor
ImageColor.getcolor("Green","RGB")
Out[11]:
(0, 128, 0)
In [12]:
img_rotate = img.rotate(60,expand=True,
fillcolor= ImageColor.getcolor("Green","RGB")) # (0, 128, 0)
img_rotate
Out[12]:
Crop¶
Crop(( left_X , top_Y , right_X , bottom_Y ))
In [13]:
img_crop = img.crop((0,0,300,100))
img_crop
Out[13]:
In [14]:
img_crop = img.crop((200,80,260,150))
img_crop
Out[14]:
flipping the image / transpose the image¶
In [15]:
img_flip_horizontal = img.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
display(img) # original pitcure
img_flip_horizontal
Out[15]:
In [16]:
img_flip_vertical = img.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
display(img) # original picture
img_flip_vertical
Out[16]:
In [17]:
img_flip_rotate_90 = img.transpose(Image.Transpose.ROTATE_90)
display(img_flip_rotate_90)
img_flip_rotate_180 = img.transpose(Image.Transpose.ROTATE_180)
display(img_flip_rotate_180)
img_flip_rotate_270 = img.transpose(Image.Transpose.ROTATE_270)
display(img_flip_rotate_270)
In [18]:
img_flip_transpose = img.transpose(Image.Transpose.TRANSPOSE)
display(img_flip_transpose)
img_flip_transverse = img.transpose(Image.Transpose.TRANSVERSE)
display(img_flip_transverse)
Resize¶
In [19]:
width = img.size[0] # 480
height = img.size[1] # 320
img_resize = img.resize((width*2 , height*2))
img_resize
Out[19]:
Filters and Enhancements¶
Enhancement¶
Color
In [20]:
from PIL import ImageEnhance
img_color = ImageEnhance.Color(img)
display(img_color.enhance(-1))
display(img_color.enhance(0))
display(img_color.enhance(0.5))
display(img_color.enhance(1))
display(img_color.enhance(3))
Contrast
In [21]:
img_contrast = ImageEnhance.Contrast(img)
display(img_contrast.enhance(-1))
display(img_contrast.enhance(0))
display(img_contrast.enhance(0.5))
display(img_contrast.enhance(2))
display(img_contrast.enhance(10))
Brightness
In [22]:
img_brightness = ImageEnhance.Brightness(img)
display(img_brightness.enhance(0))
display(img_brightness.enhance(1))
display(img_brightness.enhance(2))
Sharpness
In [23]:
img_sharpness = ImageEnhance.Sharpness(img)
display(img_sharpness.enhance(-2))
display(img_sharpness.enhance(1))
display(img_sharpness.enhance(5))
display(img_sharpness.enhance(9))
Filter¶
BoxBlur
In [24]:
from PIL import ImageFilter
img_boxblur = img.filter(ImageFilter.BoxBlur(12))
img_boxblur
Out[24]:
GaussianBlur
In [25]:
img_gaussblur = img.filter(ImageFilter.GaussianBlur(3))
img_gaussblur
Out[25]:
UnsharpMask
In [26]:
img_unsharp = img.filter(ImageFilter.UnsharpMask(8))
img_unsharp
Out[26]:
Blur
In [27]:
img_blur = img.filter(ImageFilter.BLUR)
img_blur
Out[27]:
Contour
In [28]:
img_contour = img.filter(ImageFilter.CONTOUR)
img_contour
Out[28]:
DETAIL
In [29]:
img_detail = img.filter(ImageFilter.DETAIL)
display(img) # original picture
img_detail
Out[29]:
Edge Enchance
In [30]:
img_edge_enchance = img.filter(ImageFilter.EDGE_ENHANCE)
img_edge_enchance
Out[30]:
Edge Enchance More
In [31]:
img_edge_enchance_more = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
img_edge_enchance_more
Out[31]:
Find Edge
In [32]:
img_find_edge = img.filter(ImageFilter.FIND_EDGES)
img_find_edge
Out[32]:
Emboss
In [33]:
img_emboss = img.filter(ImageFilter.EMBOSS)
img_emboss
Out[33]:
Sharpen
In [34]:
img_sharpen = img.filter(ImageFilter.SHARPEN)
img_sharpen
Out[34]:
Smooth
In [35]:
img_smooth = img.filter(ImageFilter.SMOOTH)
img_smooth
Out[35]:
Smooth More
In [36]:
img_smooth_more = img.filter(ImageFilter.SMOOTH_MORE)
img_smooth_more
Out[36]:
Min Filter
In [37]:
img_min_filter = img.filter(ImageFilter.MinFilter(5))
img_min_filter
Out[37]:
Median Filter
In [38]:
img_median_filter = img.filter(ImageFilter.MedianFilter(5))
img_median_filter
Out[38]:
Max Filter
In [39]:
img_max_filter = img.filter(ImageFilter.MaxFilter(5))
img_max_filter
Out[39]:
Mode Filter
In [40]:
img_mode_filter = img.filter(ImageFilter.ModeFilter(5))
img_mode_filter
Out[40]:
Colors in Pillow¶
Analysing picture information¶
In [41]:
display(img.crop((0,0,1,1)).resize((30,30)))
img.getpixel((0,0))
# ( R , G , B )
Out[41]:
(245, 194, 166)
In [117]:
img.getcolors(maxcolors= img.size[0]*img.size[1])[0:10]
# showing every colors and number of used it
# ( number_of_use, ( R , G , B ))
Out[117]:
[(17, (255, 255, 255)), (1, (1, 0, 0)), (4, (254, 255, 255)), (1, (252, 255, 255)), (1, (251, 255, 251)), (7, (250, 255, 255)), (6, (249, 255, 255)), (4, (248, 255, 255)), (5, (251, 255, 255)), (2, (246, 255, 254))]
In [43]:
img.mode
Out[43]:
'RGB'
In [44]:
img.getbands()
Out[44]:
('R', 'G', 'B')
In [45]:
img.info
Out[45]:
{'dpi': (72.009, 72.009),
'xmp': b'<?xpacket begin="\xef\xbb\xbf" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 9.1-c003 79.9690a87, 2025/03/06-19:12:03 "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmp:CreatorTool="Adobe Photoshop 26.8 (Windows)" xmp:CreateDate="2025-07-24T11:53:08+03:30" xmp:ModifyDate="2025-07-25T09:19:21+03:30" xmp:MetadataDate="2025-07-25T09:19:21+03:30" dc:format="image/png" photoshop:ColorMode="3" xmpMM:InstanceID="xmp.iid:f0f5ae2e-565e-964d-baee-d2480d24f523" xmpMM:DocumentID="xmp.did:eac1155c-5760-5b4c-864e-4987de78e248" xmpMM:OriginalDocumentID="xmp.did:eac1155c-5760-5b4c-864e-4987de78e248"> <xmpMM:History> <rdf:Seq> <rdf:li stEvt:action="created" stEvt:instanceID="xmp.iid:eac1155c-5760-5b4c-864e-4987de78e248" stEvt:when="2025-07-24T11:53:08+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)"/> <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:be8255f3-87b7-7e47-8ffe-9224bc1851ae" stEvt:when="2025-07-24T13:12:18+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)" stEvt:changed="/"/> <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:f0f5ae2e-565e-964d-baee-d2480d24f523" stEvt:when="2025-07-25T09:19:21+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)" stEvt:changed="/"/> </rdf:Seq> </xmpMM:History> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>',
'XML:com.adobe.xmp': '<?xpacket begin="\ufeff" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 9.1-c003 79.9690a87, 2025/03/06-19:12:03 "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmp:CreatorTool="Adobe Photoshop 26.8 (Windows)" xmp:CreateDate="2025-07-24T11:53:08+03:30" xmp:ModifyDate="2025-07-25T09:19:21+03:30" xmp:MetadataDate="2025-07-25T09:19:21+03:30" dc:format="image/png" photoshop:ColorMode="3" xmpMM:InstanceID="xmp.iid:f0f5ae2e-565e-964d-baee-d2480d24f523" xmpMM:DocumentID="xmp.did:eac1155c-5760-5b4c-864e-4987de78e248" xmpMM:OriginalDocumentID="xmp.did:eac1155c-5760-5b4c-864e-4987de78e248"> <xmpMM:History> <rdf:Seq> <rdf:li stEvt:action="created" stEvt:instanceID="xmp.iid:eac1155c-5760-5b4c-864e-4987de78e248" stEvt:when="2025-07-24T11:53:08+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)"/> <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:be8255f3-87b7-7e47-8ffe-9224bc1851ae" stEvt:when="2025-07-24T13:12:18+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)" stEvt:changed="/"/> <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:f0f5ae2e-565e-964d-baee-d2480d24f523" stEvt:when="2025-07-25T09:19:21+03:30" stEvt:softwareAgent="Adobe Photoshop 26.8 (Windows)" stEvt:changed="/"/> </rdf:Seq> </xmpMM:History> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>'}
channels¶
In [46]:
img.getchannel("R")
Out[46]:
In [47]:
img.getchannel("G")
Out[47]:
In [48]:
img.getchannel("B")
Out[48]:
numpy section
In [120]:
import numpy as np
display(np.array(img).shape) # ( img.size[1] , img.size[0] , RGB )
np.array(img)[0][0:10]
# [[ R ] , [ G ] , [ B ]]
(200, 300, 3)
Out[120]:
array([[245, 194, 166],
[247, 182, 152],
[247, 202, 191],
[223, 196, 88],
[232, 182, 0],
[188, 154, 60],
[207, 192, 153],
[227, 185, 3],
[235, 200, 5],
[242, 206, 0]], dtype=uint8)
In [50]:
np.array(img.getchannel('R'))
Out[50]:
array([[245, 247, 247, ..., 246, 245, 245],
[244, 253, 231, ..., 245, 246, 247],
[248, 250, 217, ..., 246, 244, 246],
...,
[246, 247, 247, ..., 244, 244, 246],
[247, 250, 247, ..., 245, 247, 246],
[245, 247, 250, ..., 246, 246, 245]], shape=(200, 300), dtype=uint8)
Color converstions¶
In [51]:
img_grayscale_1bit = img.convert('1')
img_grayscale_1bit
Out[51]:
In [52]:
np.array(img_grayscale_1bit,dtype=int)
Out[52]:
array([[1, 1, 1, ..., 1, 1, 1],
[1, 1, 0, ..., 1, 1, 0],
[1, 1, 1, ..., 1, 1, 1],
...,
[1, 1, 1, ..., 1, 1, 1],
[1, 0, 1, ..., 1, 0, 1],
[1, 1, 1, ..., 1, 1, 1]], shape=(200, 300))
In [53]:
img_grayscale_l = img.convert('L')
img_grayscale_l
Out[53]:
In [54]:
# np.array(img) == img.getbands()
In [55]:
img_palette = img.convert('P')
img_palette
Out[55]:
In [56]:
np.array(img_palette.getpalette())
Out[56]:
array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 102, 0, 0,
153, 0, 0, 204, 0, 0, 255, 0, 0, 0, 51, 0, 51,
51, 0, 102, 51, 0, 153, 51, 0, 204, 51, 0, 255, 51,
0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0,
204, 102, 0, 255, 102, 0, 0, 153, 0, 51, 153, 0, 102,
153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 0, 0, 204,
0, 51, 204, 0, 102, 204, 0, 153, 204, 0, 204, 204, 0,
255, 204, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153,
255, 0, 204, 255, 0, 255, 255, 0, 0, 0, 51, 51, 0,
51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 51,
0, 51, 51, 51, 51, 51, 102, 51, 51, 153, 51, 51, 204,
51, 51, 255, 51, 51, 0, 102, 51, 51, 102, 51, 102, 102,
51, 153, 102, 51, 204, 102, 51, 255, 102, 51, 0, 153, 51,
51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255,
153, 51, 0, 204, 51, 51, 204, 51, 102, 204, 51, 153, 204,
51, 204, 204, 51, 255, 204, 51, 0, 255, 51, 51, 255, 51,
102, 255, 51, 153, 255, 51, 204, 255, 51, 255, 255, 51, 0,
0, 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0,
102, 255, 0, 102, 0, 51, 102, 51, 51, 102, 102, 51, 102,
153, 51, 102, 204, 51, 102, 255, 51, 102, 0, 102, 102, 51,
102, 102, 102, 102, 102, 153, 102, 102, 204, 102, 102, 255, 102,
102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102,
204, 153, 102, 255, 153, 102, 0, 204, 102, 51, 204, 102, 102,
204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 102, 0, 255,
102, 51, 255, 102, 102, 255, 102, 153, 255, 102, 204, 255, 102,
255, 255, 102, 0, 0, 153, 51, 0, 153, 102, 0, 153, 153,
0, 153, 204, 0, 153, 255, 0, 153, 0, 51, 153, 51, 51,
153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 153,
0, 102, 153, 51, 102, 153, 102, 102, 153, 153, 102, 153, 204,
102, 153, 255, 102, 153, 0, 153, 153, 51, 153, 153, 102, 153,
153, 153, 153, 153, 204, 153, 153, 255, 153, 153, 0, 204, 153,
51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255,
204, 153, 0, 255, 153, 51, 255, 153, 102, 255, 153, 153, 255,
153, 204, 255, 153, 255, 255, 153, 0, 0, 204, 51, 0, 204,
102, 0, 204, 153, 0, 204, 204, 0, 204, 255, 0, 204, 0,
51, 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51,
204, 255, 51, 204, 0, 102, 204, 51, 102, 204, 102, 102, 204,
153, 102, 204, 204, 102, 204, 255, 102, 204, 0, 153, 204, 51,
153, 204, 102, 153, 204, 153, 153, 204, 204, 153, 204, 255, 153,
204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204,
204, 204, 204, 255, 204, 204, 0, 255, 204, 51, 255, 204, 102,
255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 204, 0, 0,
255, 51, 0, 255, 102, 0, 255, 153, 0, 255, 204, 0, 255,
255, 0, 255, 0, 51, 255, 51, 51, 255, 102, 51, 255, 153,
51, 255, 204, 51, 255, 255, 51, 255, 0, 102, 255, 51, 102,
255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 102, 255,
0, 153, 255, 51, 153, 255, 102, 153, 255, 153, 153, 255, 204,
153, 255, 255, 153, 255, 0, 204, 255, 51, 204, 255, 102, 204,
255, 153, 204, 255, 204, 204, 255, 255, 204, 255, 0, 255, 255,
51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255,
255, 255])
In [57]:
img_palette_6 = img.convert('P',palette= Image.Palette.ADAPTIVE,colors=6)
img_palette_6
Out[57]:
In [58]:
new_palette = [ x // 2 for x in img_palette_6.getpalette()]
img_palette_6.putpalette(new_palette)
img_palette_6
Out[58]:
In [59]:
Image.MODES
Out[59]:
['1', 'CMYK', 'F', 'HSV', 'I', 'I;16', 'I;16B', 'I;16L', 'I;16N', 'L', 'LA', 'La', 'LAB', 'P', 'PA', 'RGB', 'RGBA', 'RGBa', 'RGBX', 'YCbCr']
put pixel
In [60]:
img_putpixel = img.crop((0,0,40,40))
for num in range(1,18):
img_putpixel.putpixel((20,20 + num ),(255,0,0))
img_putpixel.putpixel((21,20 + num ),(255,0,0))
img_putpixel.putpixel((22,20 + num ),(255,0,0))
img_putpixel.putpixel((21,26),(0,0,255))
img_putpixel.resize((200,200))
Out[60]:
In [61]:
new_img = img.copy()
for x in range(new_img.size[0]):
for y in range(new_img.size[1]):
if new_img.getpixel((x,y))[0] > 240:
new_img.putpixel((x,y),(0,0,255))
new_img
Out[61]:
ImageOps works kinda like a filter but it can do more¶
color change¶
In [62]:
from PIL import ImageOps
ImageOps.autocontrast(img,cutoff= 4)
Out[62]:
In [63]:
ImageOps.invert(img)
Out[63]:
In [64]:
ImageOps.solarize(img,threshold=190)
Out[64]:
In [65]:
ImageOps.posterize(img,bits=2)
Out[65]:
In [66]:
ImageOps.grayscale(img)
Out[66]:
In [67]:
ImageOps.equalize(img)
Out[67]:
In [68]:
ImageOps.colorize(img.convert('L'),black="yellow",white='red',blackpoint=50)
Out[68]:
dimension changes¶
In [69]:
ImageOps.mirror(img) # img.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
Out[69]:
In [70]:
ImageOps.flip(img) # img.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
Out[70]:
In [71]:
ImageOps.scale(img,factor= 0.4)
# img.resize((int(img.size[0]*0.4),int(img.size[1]*0.4)))
Out[71]:
In [72]:
ImageOps.contain(img,size=(200,200))
Out[72]:
Adding and removing¶
In [73]:
ImageOps.expand(img,border=(25,6),fill='green')
Out[73]:
In [74]:
ImageOps.pad(img ,size=(400,200),color="red")
Out[74]:
In [75]:
ImageOps.fit(img,size=(100,200))
Out[75]:
In [76]:
ImageOps.crop(img,border=60)
Out[76]:
diformer¶
In [77]:
class Diformer:
def getmesh(self,img : Image):
width , height = img.size
soures_shape = (0,0 # ┌─
,0,height # └─
,width,height # ─┘
,width,0) # └─
target_rect = (0,0,width //2,height)
return [(target_rect,soures_shape)]
ImageOps.deform(img,Diformer())
Out[77]:
In [78]:
class Diformer:
def getmesh(self,img : Image):
width , height = img.size
soures_shape = (0,0 # ┌─
,0,height # └─
,width - 200,height # ─┘
,width,0) # └─
target_rect = (0,0,width //2,height)
return [(target_rect,soures_shape)]
ImageOps.deform(img,Diformer())
Out[78]:
In [79]:
class Diformer:
def getmesh(self,img : Image):
width , height = img.size
# (0,0) ┌─
# (w,h) ─┘
left = (0,0, width//2 ,height),(0,0,0,height,width//2,height,width//2,0)
right = (width//2 ,0,width,height),(width//2,0,width//2,height,0,height,0,0)
return [left,right]
ImageOps.deform(img,Diformer())
Out[79]:
In [80]:
class Diformer:
def getmesh(self,img : Image):
width , height = img.size
# (0,0) ┌─
# (w,h) ─┘
left = (0,0, width//2 ,height),(0,0,0,height,width//2,height,width//2,0)
right = (width//2 ,0,width,height),(width//2,height,width//2,0,width,0,width,height)
return [left,right]
ImageOps.deform(img,Diformer())
Out[80]:
In [81]:
class Diformer:
def transform(self, x , y):
import math
y = y + 30*math.sin(x/40)
return x , y
def transform_rectangle(self,x0,y0,x1,y1):
return ( *self.transform(x0,y0),
*self.transform(x0,y1),
*self.transform(x1,y1),
*self.transform(x1,y0),)
def getmesh(self,img : Image):
width , height = img.size
gridspace = 20
target_grid = []
for x in range(0,width,gridspace):
for y in range(0,height,gridspace):
target_grid.append((x,y,x+gridspace,y+gridspace))
source_grid = [ self.transform_rectangle(*rect) for rect in target_grid]
return [ t for t in zip(target_grid,source_grid)]
ImageOps.deform(img,Diformer())
Out[81]:
Drawing shapes¶
In [82]:
from PIL import ImageDraw
new_img = img.copy()
draw = ImageDraw.Draw(new_img)
draw.rectangle((30,30,100,180),width=3)
new_img
Out[82]:
In [83]:
draw.rectangle((30,30,100,180),width=3 , outline='yellow',fill='green')
new_img
Out[83]:
In [84]:
draw.ellipse((33,33,97,176),width=0 ,fill='purple')
new_img
Out[84]:
In [85]:
draw.polygon(((120,40),(176,20),(200,56),(176,70)),width=4,fill='blue',outline="white")
new_img
Out[85]:
In [86]:
draw.line(((170,180),(289,160),(250,40)),fill="black",width=5,joint='curve')
new_img
Out[86]:
In [87]:
draw.arc((170,100,220,150),start=20,end=200,width=5,fill='yellow')
new_img
Out[87]:
In [88]:
draw.chord((170,100,220,150),start=20,end=200,width=5,fill='yellow')
new_img
Out[88]:
In [89]:
draw.pieslice((170,100,220,150),start=40,end=80,width=5,fill='green')
new_img
Out[89]:
In [90]:
from PIL import ImageFont
font = ImageFont.truetype(font='arial',size=20)
draw.text((40,50),'fruits',font=font,fill='red')
new_img
Out[90]:
Combining images¶
merging images with Image.mehods( )¶
In [91]:
picture = Image.open('picture.jpg')
picture
Out[91]:
In [92]:
# both images need same size and mode
Image.blend(img,picture,0.6)
Out[92]:
In [93]:
Image.composite(img,picture,mask= Image.new('L',img.size,100))
Out[93]:
image paste¶
In [94]:
python = Image.open("python.png")
python
Out[94]:
In [95]:
new_img = img.copy()
new_img.paste(python,(100,50),mask=python)
new_img
Out[95]:
channel operations¶
In [96]:
from PIL import ImageChops
ImageChops.overlay(img,picture)
Out[96]:
In [97]:
ImageChops.darker(img,picture)
Out[97]:
In [98]:
ImageChops.lighter(img,picture)
Out[98]:
In [99]:
ImageChops.soft_light(img,picture)
Out[99]:
In [100]:
ImageChops.hard_light(img,picture)
Out[100]:
In [101]:
ImageChops.difference(img,picture)
Out[101]:
In [102]:
ImageChops.add_modulo(img,picture)
Out[102]:
In [103]:
ImageChops.screen(img,picture)
Out[103]:
In [104]:
ImageChops.multiply(img,picture)
Out[104]:
more complex channel operations¶
In [105]:
ImageChops.add(img,picture,scale=3,offset=100)
Out[105]:
In [106]:
ImageChops.add(img,picture,scale=2,offset=20)
Out[106]:
In [107]:
ImageChops.subtract(img,picture,scale=2,offset=100)
Out[107]:
logical¶
In [108]:
ImageChops.logical_and(img.convert('1'),picture.convert('1'))
Out[108]:
In [109]:
ImageChops.logical_or(img.convert('1'),picture.convert('1'))
Out[109]:
In [110]:
ImageChops.logical_xor(img.convert('1'),picture.convert('1'))
Out[110]:
masking¶
In [111]:
mask = Image.open("mask.png")
Image.open("mask.png").convert('L')
Out[111]:
In [112]:
img_masked_alpha = Image.alpha_composite(img.convert("RGBA"),mask)
img_masked_alpha
Out[112]:
In [113]:
img_masked = Image.composite(img,picture,mask=mask)
img_masked
Out[113]:
In [114]:
img_masked = Image.composite(img,picture,mask=mask.convert('L'))
img_masked
Out[114]: